package com.ficus.road.maintain.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.ficus.road.maintain.config.DiseaseConfig;
import com.ficus.road.maintain.config.DiseaseConfigInfo;
import com.ficus.road.maintain.core.model.*;
import com.ficus.road.maintain.core.model.taskInfo.TaskInfoDetail;
import com.ficus.road.maintain.core.model.taskInfo.TaskInfoResponse;
import com.ficus.road.maintain.core.utils.JsonUtils;
import com.ficus.road.maintain.dao.*;
import com.ficus.road.maintain.operationlog.annotation.OpLog;
import com.ficus.road.maintain.util.ZHTokenUtil;
import com.google.common.collect.Maps;
import ficus.car_demo.FrameMeta;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.ficus.road.maintain.core.model.HitStatusEnum.NEW;

@Component
@Slf4j
public class ZhonghaiClient {

    public static final String ZH_METHOD_WORK_CHECK = "ytkjWorkCheck";
    public static final String ZH_METHOD_ASSESSMENT_SCORE = "ytkjAssessmentScore";
    public static final String ZH_METHOD_SMART_DISCOVER = "ytkjSmartDiscover";
    public static final String ZH_METHOD_COMPLAIN_REPORT = "ytkjComplainReportLarge";
    public static final String ZH_METHOD_UNIT_SCORE = "ytkjQueryScore";

    // 添加获取案卷流程信息接口
    public static final String ZH_METHOD_GET_ADVICE = "ytkjGetAdvice";

    private static final String template = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
            "<SOAP-ENV:Body>%s" +
            "</SOAP-ENV:Body>" +
            "</SOAP-ENV:Envelope>";
    @Autowired
    ZHTokenUtil zhTokenUtil;
    @Autowired
    HitDao hitDao;
    @Autowired
    UnitDao unitDao;
    @Autowired
    OperationLogDao operationLogDao;
    @Autowired
    CompanyDao companyDao;
    @Autowired
    CompanyService companyService;
    @Autowired
    CarService carService;
    @Autowired
    DiseaseConfig diseaseConfig;
    @Autowired
    ZhonghaiClient zhonghaiClient;
    @Autowired
    ZhongHaiDao zhongHaiDao;
    @Autowired
    CjyhClient cjyhClient;
    @Autowired
    private InspectPictureDao inspectPictureDao;
    @Value("${zhonghai.ip}")
    private String ip;
    @Value("${zhonghai.port}")
    private int port;
    @Value("${xlj.server}")
    private String server;
    @Value("${zhonghai.webServicePort}")
    private int webServicePort;
    @Value("${zhonghai.username}")
    private String username;
    @Value("${present.flag}")
    private Boolean present;
    @Value("${hit-config.merge-distance}")
    private int mergeDistance;
    private Socket socket;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    private SimpleDateFormat ymSdf = new SimpleDateFormat("yyyy-MM");
    @Getter
    private Map<String, Map<String, CompanyScoreResponse>> companyScoreResponseMap = Maps.newHashMap();

    public static String getWebserviceResponse(String url, String method, String data, String header) throws Exception {
        byte[] buf = data.getBytes();
        URL uri = new URL(url);
        HttpURLConnection httpConn = (HttpURLConnection) uri.openConnection();
        httpConn.setRequestMethod(method);
        httpConn.setRequestProperty("Content-Type", "application/json");
        httpConn.setRequestProperty("Content-Length", String.valueOf(buf.length));
        if (header != null && !header.equals("")) {
            httpConn.setRequestProperty("Authorization", header);
        }
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);
        httpConn.setChunkedStreamingMode(0);
        httpConn.setConnectTimeout(10000);
        httpConn.setReadTimeout(10000);
//        httpConn.connect();
        OutputStream out = httpConn.getOutputStream();
        out.write(buf);
        out.close();
        int code = httpConn.getResponseCode();
        StringBuilder sb = new StringBuilder();
        if (code == HttpURLConnection.HTTP_OK) {
            InputStreamReader isr = new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            sb = new StringBuilder();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
            isr.close();
        } else {
            throw new Exception("中海状态码异常, 状态码: " + code);
//            log.info("状态码： {}", code);
//            InputStreamReader isr = new InputStreamReader(httpConn.getErrorStream(), "utf-8");
//            BufferedReader br = new BufferedReader(isr);
//            sb = new StringBuilder();
//            String str;
//            while ((str = br.readLine()) != null) {
//                sb.append(str).append("\r\n");
//            }
//            br.close();
//            isr.close();
        }
        return sb.toString();
    }

    public static String getDataFromZhonghai(String url, String method, String data, String header) throws IOException {
        byte[] buf = data.getBytes();
        URL uri = new URL(url);
        HttpURLConnection httpConn = (HttpURLConnection) uri.openConnection();
        httpConn.setRequestMethod(method);
        httpConn.setRequestProperty("Content-Type", "application/json");
        httpConn.setRequestProperty("Content-Length", String.valueOf(buf.length));
        //设置超时时间
        httpConn.setConnectTimeout(10000);
        httpConn.setReadTimeout(10000);
        if (header != null && !header.equals("")) {
            httpConn.setRequestProperty("Authorization", header);
        }
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);
        OutputStream out = httpConn.getOutputStream();
        out.write(buf);
        out.close();
        int code = httpConn.getResponseCode();
        StringBuilder sb;
        if (code == HttpURLConnection.HTTP_OK) {
            InputStreamReader isr = new InputStreamReader(httpConn.getInputStream(), StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            sb = new StringBuilder();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            br.close();
            isr.close();
        } else {
            log.info("状态码： {}", code);
            return new String();
        }
        return sb.toString();
    }

    /**
     * 更新城市道路数据,每月最后一日的上午3:15触发
     */
//    @Scheduled(cron = "0 15 3 10 * ?", zone = "GMT+8:00")
//    public void refreshCityRoads() {
//        String cityRoads = getCityRoads();
//        if (ObjectUtils.isNotEmpty(cityRoads)) {
//            JSONArray jsonArray = JSON.parseArray(cityRoads);
//            for (int i = 0; i < jsonArray.size(); i++) {
//                JSONObject jsonObject = jsonArray.getJSONObject(i);
//                String town = jsonObject.getString("town");
//                String roadid = jsonObject.getString("roadid");
//                String towncode = jsonObject.getString("towncode");
//                if (StringUtils.isNotBlank(towncode) && StringUtils.isNotBlank(roadid)) {
//                    String length = jsonObject.getString("length");
//                    JSONObject geojsonWgs84 = jsonObject.getJSONObject("geojsonWgs84");
//                    String roadName = jsonObject.getString("roadname");
////                String unitId = jsonObject.getString("projectid");
//                    String companyName = jsonObject.getString("unitid");
//                    RoadInfo roadInfo = roadInfoDao.fetch(roadid + towncode);
//                    if (roadInfo == null) {
//                        roadInfo = new RoadInfo();
//                    }
//                    if (geojsonWgs84 != null && geojsonWgs84.getJSONObject("geometry") != null && geojsonWgs84.getJSONObject("geometry").getJSONArray("coordinates") != null) {
//                        JSONArray coordinatesArray = geojsonWgs84.getJSONObject("geometry").getJSONArray("coordinates");
//                        List<Coordinate> points = new ArrayList<>();
//                        for (int j = 0; j < coordinatesArray.size(); j++) {
//                            JSONArray jsonArray1 = coordinatesArray.getJSONArray(j);
//                            Coordinate coordinate = new Coordinate(jsonArray1.getString(0), jsonArray1.getString(1));
//                            points.add(coordinate);
//                        }
//                        roadInfo.setCoordinates(points);
//                    }
//                    roadInfo.setRoadName(roadName);
//                    roadInfo.setId(roadid + towncode);
//                    roadInfo.setRoadType(RoadTypeEnum.HIGHWAY);
////                if (StringUtils.isNotBlank(unitId) && unitId.startsWith("YHGL")) {
////                    roadInfo.setRoadType(RoadTypeEnum.DIRECT);
////                } else {
////                    roadInfo.setRoadType(RoadTypeEnum.HIGHWAY);
////                }
//                    roadInfo.setSecNum(roadid);
//                    roadInfo.setDistrictId(towncode);
//                    if (NumberUtils.isCreatable(length)) {
//                        Double secLen = Double.valueOf(length);
//                        roadInfo.setSecLen(String.valueOf(secLen / 1000));
//                    } else {
//                        roadInfo.setSecLen("0");
//                    }
////                if(StringUtils.isNotBlank(uni))
////                roadInfo.setUnitId(unitId);
//                    roadInfo.setCompanyName(companyName);
//                    roadInfo.setTown(town);
//                    roadInfoDao.saveOrUpdate(roadInfo);
//                }
//            }
//        }
//        log.info("调用中海接口更新城市道路数据成功!");
//    }

    /**
     * 更新道路基础信息
     */
//    @Scheduled(cron = "0 25 3 10 * ?", zone = "GMT+8:00")
//    public void refreshRoadBasicInfo() {
//        String basicInfos = getRoadBasicInfo();
////        Map<String, String> townNameIdMap = districtDao.findAll().stream().collect(Collectors.toMap(District::getName, District::getId));
////        List<BasicRoadInfoZH> roadInfoZH = JSONArray.parseArray(basicInfos, BasicRoadInfoZH.class);
////        roadInfoZH.forEach(zh -> {
////            new Query(Criteria.where("id").is(zh.getRoadid() + ));
////        });
//        if (ObjectUtils.isNotEmpty(basicInfos)) {
//            JSONArray jsonArray = JSON.parseArray(basicInfos);
//            for (int i = 0; i < jsonArray.size(); i++) {
//                JSONObject jsonObject = jsonArray.getJSONObject(i);
//                String towncode = jsonObject.getString("towncode");
//                String roadId = jsonObject.getString("roadid");
//                String roadName = jsonObject.getString("roadname");
//                Criteria criteria = Criteria.where("district_id").is(towncode);
//                if (StringUtils.isNotBlank(roadId)) {
//                    criteria.and("sec_num").is(roadId);
//                } else {
//                    criteria.and("road_name").is(roadName);
//                }
//                String roadType = jsonObject.getString("roadtype");
//                RoadTypeEnum newRoadType = RoadTypeEnum.ROAD;
//                if (roadType.equals("城市道路")) {
//                    criteria.and("road_type").is(RoadTypeEnum.HIGHWAY.toString());
//                    newRoadType = RoadTypeEnum.HIGHWAY;
//                } else if (roadType.equals("直管公路")) {
//                    criteria.and("road_type").is(RoadTypeEnum.DIRECT.toString());
//                    newRoadType = RoadTypeEnum.DIRECT;
//                } else if (roadType.equals("农村公路")) {
//                    criteria.and("road_type").is(RoadTypeEnum.ROAD.toString());
//                    newRoadType = RoadTypeEnum.ROAD;
//                } else {
//                    System.out.println(222);
//                }
//                List<RoadInfo> byQuery = roadInfoDao.findByQuery(new Query(criteria));
//
//                if (byQuery.size() == 1) {
//                    if (!roadType.equals("农村公路")) {
//                        RoadInfo roadInfo = byQuery.get(0);
//                        String companyName = jsonObject.getString("unitid");
//                        String companyId = jsonObject.getString("unitidcode");
//                        String startEndPoint = jsonObject.getString("roadrangedesc");
//                        String area = jsonObject.getString("area");
//                        String startlocation = jsonObject.getString("startlocation");
//                        String endlocation = jsonObject.getString("endlocation");
//                        String length = jsonObject.getString("length");
//                        String unitId = jsonObject.getString("projectid");
//
//                        roadInfo.setCompanyId(companyId);
//                        roadInfo.setCompanyName(companyName);
//                        roadInfo.setRoadType(newRoadType);
//                        roadInfo.setUnitId(unitId);
//                        roadInfo.setSecLen(length);
//                        roadInfo.setSecArea(area);
//                        roadInfo.setStartEndPoint(startEndPoint);
//                        roadInfo.setStartStake(startlocation);
//                        roadInfo.setEndStake(endlocation);
//                        roadInfoDao.saveOrUpdate(roadInfo);
//                    }
//                }
//
//                String companyName = jsonObject.getString("unitid");
//                String companyId = jsonObject.getString("unitidcode");
//                String unitId = jsonObject.getString("projectid");
//                if (StringUtils.isNotBlank(companyId)) {
//                    Company fetch = companyDao.fetch(companyId);
//                    if (fetch == null) {
//                        fetch = new Company();
//                        fetch.setId(companyId);
//                        if (StringUtils.isNotBlank(companyName) && companyName.length() > 6) {
//                            fetch.setName(companyName);
//                        } else {
//                            fetch.setShortName(companyName);
//                        }
//                        fetch.setUnits(Set.of(unitId));
//                    } else {
//                        if (StringUtils.isNotBlank(companyName) && companyName.length() > 6) {
//                            fetch.setName(companyName);
//                        } else {
//                            fetch.setShortName(companyName);
//                        }
//                        Set<String> units = fetch.getUnits();
//                        if (units.isEmpty()) {
//                            units = new HashSet<>();
//                        }
//                        units.add(unitId);
//                        fetch.setUnits(units);
//                    }
//                    companyDao.saveOrUpdate(fetch);
//                }
//            }
//        }
//        log.info("调用中海接口更新道路基础数据成功!");
//    }

    // 算一天的病害密度
//    public String getUnitDiseaseDensity(String startDate, String endDate) {
//        String token = getLocalToken();
//        String authorization = getAuthorization(token);
//        String host = ip + ":" + webServicePort + "/hbzs/";
//        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
//                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
//                "<SOAP-ENV:Body>%s" +
//                "</SOAP-ENV:Body>" +
//                "</SOAP-ENV:Envelope>";
//        String data = String.format(dataTemplate, "<m:hbzptInfo" +
//                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
//                "<arg0>ytkjGetSectionBhRate</arg0>" +
//                "<arg1>{'startDate':'" + startDate + "','endDate':'" + startDate + "'}</arg1>" +
//                "</m:hbzptInfo>");
//        String rlt = null;
//        try {
//            rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
//        } catch (Exception e) {
//            log.error("调用中海接口获取标段病害密度信息异常！");
//            return null;
//        }
//        log.info("调用中海接口获取标段病害密度信息成功！");
//        int startIndex = rlt.indexOf("<return>") + 8;
//        int endIndex = rlt.indexOf("</return>", startIndex);
//        if (startIndex + 10 >= endIndex - 3) {
//            return null;
//        }
//        String roadInfo = rlt.substring(startIndex, endIndex);
//        return roadInfo;
//    }

//    public String getRoadCoverage() {
//        String token = getLocalToken();
//        String authorization = getAuthorization(token);
//        String host = ip + ":" + webServicePort + "/hbzs/";
//        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
//                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
//                "<SOAP-ENV:Body>%s" +
//                "</SOAP-ENV:Body>" +
//                "</SOAP-ENV:Envelope>";
//        String data = String.format(dataTemplate, "<m:hbzptInfo" +
//                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
//                "<arg0>ytkjRoadDayCover</arg0>" +
//                "<arg1>{}</arg1>" +
//                "</m:hbzptInfo>");
//        String rlt = null;
//        try {
//            rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
//        } catch (Exception e) {
//            log.error("调用中海接口获取道路覆盖率异常！");
//            return null;
//        }
//        log.info("调用中海接口获取道路覆盖率成功！");
//        int startIndex = rlt.indexOf("<return>") + 8;
//        int endIndex = rlt.indexOf("</return>", startIndex);
//        if (startIndex + 10 >= endIndex - 3) {
//            return null;
//        }
//        String roadInfo = rlt.substring(startIndex, endIndex);
//        return roadInfo;
//    }

//    public String getRoadDiseaseDensity(String startDate, String endDate) {
//        String token = getLocalToken();
//        String authorization = getAuthorization(token);
//        String host = ip + ":" + webServicePort + "/hbzs/";
//        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
//                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
//                "<SOAP-ENV:Body>%s" +
//                "</SOAP-ENV:Body>" +
//                "</SOAP-ENV:Envelope>";
//        String data = String.format(dataTemplate, "<m:hbzptInfo" +
//                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
//                "<arg0>ytkjGetRoadBhRate</arg0>" +
//                "<arg1>{'startTime':'" + startDate + "','endTime':'" + endDate + "'}</arg1>" +
//                "</m:hbzptInfo>");
//        String rlt = null;
//        try {
//            rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
//        } catch (Exception e) {
//            log.error("调用中海接口获取道路病害密度信息异常！");
//            return null;
//        }
//        log.info("调用中海接口获取道路病害密度信息成功！");
//        int startIndex = rlt.indexOf("<return>") + 8;
//        int endIndex = rlt.indexOf("</return>", startIndex);
//        if (startIndex + 10 >= endIndex - 3) {
//            return null;
//        }
//        String roadInfo = rlt.substring(startIndex, endIndex);
//        return roadInfo;
//    }
    @PostConstruct
    public void init() throws Exception {
//        List<Hit> byQuery = hitDao.findHitBySmart(new Query(Criteria.where("attrs.status").is("DISPATCHED").and("attrs.confirmation.status").is("CORRECT").and("first_hit_time").gt(1643175859)));
//        for (Hit hit : byQuery) {
//            if (hit.getList().size() == 2) {
//                if (hit.getList().get(0).getAttrs().getStatus().equals(NEW)) {
//                    List<HistoryHit> list = new ArrayList<>();
//                    list.add(hit.getList().get(1));
//                    list.add(hit.getList().get(0));
//                    hit.setList(list);
//                    hitDao.saveOrUpdate(hit);
//                }
//            }
//        }
//        RoadSection roadSection = roadSectionDao.fetch("611b7ab7173d63fe1fcd665b");
//        String gaodeLocation = roadSection.getGaodeLocation();
//
//        List<Coordinate> coordinateList = JSONArray.parseArray(gaodeLocation, Coordinate.class);
//        List<Coordinate> wgspoints = coordinateList.stream().map(item -> {
//            String x = item.getX();
//            String y = item.getY();
//            double[] doubles = LngLonUtil.gcj02towgs84(Double.valueOf(x), Double.valueOf(y));
//            Coordinate coordinate = new Coordinate(String.valueOf(doubles[0]), String.valueOf(doubles[1]));
//            return coordinate;
//        }).collect(Collectors.toList());
//        RoadInfo s121TANGZHEN = roadInfoDao.fetch("S222HEQING");
//        s121TANGZHEN.setCoordinates(wgspoints);
//        roadInfoDao.saveOrUpdate(s121TANGZHEN);

//        Date date = sdfDate.parse("2022-01-17");
//        Date date1 = sdfDate.parse("2022-01-24");
//        Criteria criteria = Criteria.where("operate_date").gt(date).lt(date1).and("title").is("中海回调");
//        List<OperationLog> byQuery = operationLogDao.findHitBySmart(new Query(criteria));
//        Set<String> hitIds = new HashSet<>();
//        for (OperationLog log : byQuery) {
//            Object request = log.getRequest();
//            String s = JSONObject.toJSONString(request);
//            JSONObject updateHitStatusRequest = JSONObject.parseObject(s).getJSONObject("updateHitStatusRequest");
//            String hitId = JSONObject.parseObject(s).getString("hitId");
//            String sectionCode = updateHitStatusRequest.getString("sectionCode");
//            if (sectionCode != null && sectionCode.startsWith("YHGL")) {
//                System.out.println(hitId + ":" + sectionCode);
//                hitIds.add(hitId);
//            }
//            System.out.println(hitIds.size());
//        }
//        Point point = new Point(121.59991725, 31.238922236);
//        List<AggregationOperation> aggregationList = new ArrayList<>();
//        aggregationList.add(new GeoNearDocument(new Query(Criteria.where("car_id").in(Lists.newArrayList("YTKJ20210069")).and("timestamp").gt(1642830443)), point, "location", mergeDistance));
//        Aggregation agg = Aggregation.newAggregation(
//                aggregationList);
//        System.out.println("111");
//        List<Unit> all = unit1Dao.findAll();
//        for (Unit unit : all) {
//            Unit fetch = unitDao.fetch(unit.getId());
//            if (fetch != null) {
//                fetch.setUnitName(unit.getUnitName());
//                unitDao.saveOrUpdate(fetch);
//            } else {
//                System.out.println("id:" + unit.getId());
//                unitDao.saveOrUpdate(unit);
//            }
//        }
//        System.out.println("xx");
//        refreshRoadBasicInfo();

//        List<District> all = districtDao.findAll();
//        for (District district : all) {
////            Double directLength = district.getDirectLength() != null ? district.getDirectLength() : 0d;
////            Double highwayLength = district.getHighwayLength() != null ? district.getHighwayLength() : 0d;
////            Double roadLength = district.getRoadLength() != null ? district.getRoadLength() : 0d;
//            district.setTotalLength((Math.round(district.getTotalLength() * 100) * 1.0 / 100));
//            districtDao.saveOrUpdate(district);
//        }

        // 直管公路信息, 现在需要通过excel数据手动更新
//        refreshDirectRoad();
        // 城市道路信息 (非直管公路)
//        refreshCityRoads();
        // 乡村道路信息 (非直管公路)
//        refreshDistrictRoads();
        // 道路基础信息
//        refreshRoadBasicInfo();
        // 标段病害密度
//        refreshUnitDiseaseDensityAndCoverage();
        // 道路病害密度
//        refreshRoadDiseaseDensityAndCoverage();
        // 更新pci和pqi
//        refreshPciPqi();

//        System.out.println(111);
    }

    /**
     * 朝九晚五工作时间内每半小时推送一次
     */
    @Scheduled(cron = "0 0/10 7-16 * * ?", zone = "GMT+8:00")
    public void pushConfirmedHit() {
        log.info("推送数据给中海,定时任务开始");
        if (present) {
            return;
        }
        Map<String, Map<String, Set<String>>> companyKeyPointsMap = companyService.getCompanyKeyPointsMap();
        Date date = DateUtils.addDays(new Date(), -5);
        //为了防止推送失败,将过去两天符合条件的病害进行推送
        Query query = new Query(Criteria.where("first_hit_time").gte(date.getTime() / 1000).and("attrs.status").is(NEW)
                .and("attrs.confirmation.status").is("CORRECT").and("attrs.loop").is(1));
        List<Hit> hits = hitDao.findByQuery(query);
        // 提醒件类型列表
        List<String> notedList = diseaseConfig.getNotedList();
        hits.forEach(hit -> {
            String type = hit.getType();
            DiseaseConfigInfo diseaseConfigInfo = diseaseConfig.getMap().get(type);
            if (ObjectUtils.isNotEmpty(diseaseConfigInfo)) {
                HistoryHit historyHit = hit.getList().get(0);
                Integer loop = diseaseConfigInfo.getLoop();
                Integer stype = diseaseConfigInfo.getStype();
                HistoryHit newHistoryHit = new HistoryHit();
                newHistoryHit.setHitTime(System.currentTimeMillis() / 1000);
                newHistoryHit.setSubjects(new ArrayList<>());
                newHistoryHit.setHeightDiff(historyHit.getHeightDiff());
                newHistoryHit.setAngle(historyHit.getAngle());
                newHistoryHit.setRoadType(hit.getRoadType());
                newHistoryHit.setWidth(historyHit.getWidth());
                newHistoryHit.setType(hit.getType());
                newHistoryHit.setSeverityType(hit.getSeverityType());
                newHistoryHit.setLength(historyHit.getLength());
                newHistoryHit.setHeadCount(historyHit.getHeadCount());
                newHistoryHit.setFallDownNumber(historyHit.getFallDownNumber());
                newHistoryHit.setComfortRate(historyHit.getComfortRate());
                newHistoryHit.setArea(historyHit.getArea());
                HistoryHitAttrs historyHitAttrs = new HistoryHitAttrs();
                historyHitAttrs.setSceneImage("");
                historyHitAttrs.setGpsLocation(hit.getAttrs().getGpsLocation());
                newHistoryHit.setAttrs(historyHitAttrs);
//                if (stype == 9 || stype == 32) {
                if (stype == -1) {
//                    if ((System.currentTimeMillis() / 1000 - hit.getFirstHitTime()) > 3600 * 24 * 3) {
//                        // 涉路施工直接已复核
//                        hit.getAttrs().setStatus(HitStatusEnum.CONFIRMED);
//                        newHistoryHit.getAttrs().setStatus(HitStatusEnum.CONFIRMED);
//                        hit.getList().add(0, newHistoryHit);
//                        hit.setLastModificationTime(System.currentTimeMillis() / 1000);
//                        hitService.updateHit(hit);
//                    }
                } else {
                    if (loop == 1) {
                        // 小闭环，需要推送
                        if (cjyhClient.isSupport(hit.getAttrs().getCarId()) && !hit.getAttrs().isPushCompany()) {
                            boolean b = cjyhClient.pushHit(hit);
                            if (b) {
                                hit.getAttrs().setPushCompany(true);
                                hitDao.saveOrUpdate(hit);
                            }
                        }
                        if (stype == 0) {
                            if (hit.getAttrs().getRoadType().equals(FrameMeta.RoadType.ROAD_TYPE_CEMENT.toString())) {
                                stype = 23;
                            } else if (hit.getAttrs().getRoadType().equals(FrameMeta.RoadType.ROAD_TYPE_ASPHALT.toString())) {
                                stype = 21;
                            }
                        }
                        if (ObjectUtils.isNotEmpty(hit.getAttrs().getIsPushThird()) && hit.getAttrs().getIsPushThird().equals(Boolean.TRUE)) {
                            // 已推送的病害不再推送
                            return;
                        }
                        Map map = zhonghaiClient.generateDiseaseMap(hit, stype);
                        String client = zhonghaiClient.client(map);
                        if (StringUtils.isNotEmpty(client)) {
                            try {
                                JSONObject jsonObject = JSONObject.parseObject(client);
                                if (ObjectUtils.isEmpty(jsonObject.getJSONObject("uploadResult")) ||
                                        ObjectUtils.isEmpty(jsonObject.getJSONObject("uploadResult").getJSONObject("checkData")) ||
                                        !jsonObject.getJSONObject("uploadResult").getJSONObject("checkData").getString("result").equals("0")) {
                                    log.error("send disease to zhonghai failed: {}", jsonObject);
                                } else {
                                    //推送中海成功, 推送标志位设为true, 状态不修改, 在中海回调处修改状态
                                    hit.getAttrs().setIsPushThird(Boolean.TRUE);
//                                    hit.getAttrs().setStatus(HitStatusEnum.DISPATCHED);
//                                    hit.setDispatchTime(System.currentTimeMillis() / 1000);
//                                    newHistoryHit.getAttrs().setStatus(HitStatusEnum.DISPATCHED);
//                                    hit.getList().add(0, newHistoryHit);
//                                    hit.setLastModificationTime(System.currentTimeMillis() / 1000);

                                    // 如果是提醒件 修改hit状态为已提醒
                                    if (notedList.contains(type)) {
                                        hit.getAttrs().setStatus(HitStatusEnum.NOTED);
                                        newHistoryHit.getAttrs().setStatus(HitStatusEnum.NOTED);
                                        hit.getList().add(0,newHistoryHit);
                                        hit.setLastModificationTime(System.currentTimeMillis() / 1000);
                                    }
                                    hitDao.saveOrUpdate(hit);
                                }
                            } catch (Exception e) {
                                log.error("parse zhonghai result error! {}", client);
                            }
                        }
                        //client为空，推送中海失败，不做处理

                    } else {
                        // 中大闭环, 直接改状态就可以了
                        hit.getAttrs().setStatus(HitStatusEnum.SEND);
                        hit.setDispatchTime(System.currentTimeMillis() / 1000);
                        newHistoryHit.getAttrs().setStatus(HitStatusEnum.SEND);
                        hit.getList().add(0, newHistoryHit);
                        hit.setLastModificationTime(System.currentTimeMillis() / 1000);
                        hitDao.saveOrUpdate(hit);
                    }
                }
            }
        });
    }

    public List<String> getNeighbors(GpsLocation gpsLocation) {
        List<String> result = new ArrayList<>();
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() + "_" + ((Double) (gpsLocation.getLatitude() * 1000)).intValue());
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() + "_" + (((Double) (gpsLocation.getLatitude() * 1000)).intValue() + 1));
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() + "_" + (((Double) (gpsLocation.getLatitude() * 1000)).intValue() - 1));
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() + 1 + "_" + ((Double) (gpsLocation.getLatitude() * 1000)).intValue());
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() + 1 + "_" + (((Double) (gpsLocation.getLatitude() * 1000)).intValue() + 1));
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() + 1 + "_" + (((Double) (gpsLocation.getLatitude() * 1000)).intValue() - 1));
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() - 1 + "_" + ((Double) (gpsLocation.getLatitude() * 1000)).intValue());
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() - 1 + "_" + (((Double) (gpsLocation.getLatitude() * 1000)).intValue() + 1));
        result.add(((Double) (gpsLocation.getLongitude() * 1000)).intValue() - 1 + "_" + (((Double) (gpsLocation.getLatitude() * 1000)).intValue() - 1));
        return result;
    }

    public boolean containsKey(Map map, List<String> keys) {
        for (String key : keys) {
            if (map.containsKey(key)) {
                return true;
            }
        }
        return false;
    }

//    @Scheduled(cron = "0 5 12 * * ?", zone = "GMT+8:00")
//    public void updateReviewHitStatus() {
//        if (present) {
//            return;
//        }
//        Date date = DateUtils.addDays(new Date(), -6);
//        //三天之前且状态为Complete的病害，说明之前复核病害一直失败，这里直接将状态改成Confirmed
//        Query query = new Query(Criteria.where("last_modification_time").lt(date.getTime() / 1000).and("attrs.status").is(HitStatusEnum.COMPLETE));
//        List<Hit> hits = hitDao.findHitBySmart(query);
//        hits.stream().forEach(hit -> {
//            hit.setLastModificationTime(new Date().getTime() / 1000);
//            hit.getAttrs().setStatus(HitStatusEnum.CONFIRMED);
//            hitDao.saveOrUpdate(hit);
//        });
//    }

    /**
     * 复核病害，每10分钟复核一次
     */
    @Scheduled(cron = "20 0/10 * * * ?", zone = "GMT+8:00")
//    @Scheduled(cron = "0/5 * * * * ?", zone = "GMT+8:00")
    public void reviewHit() {
        if (present) {
            return;
        }
        Query query = new Query(Criteria.where("attrs.confirmation.status").is(Confirmation.ConfirmationStatus.CORRECT).and("attrs.status").in(HitStatusEnum.COMPLETE));
        List<Hit> hits = hitDao.findByQuery(query);
        hits.forEach(hit -> {
            try {
                if (hit.getAttrs().getNeedConfirm() != null && !hit.getAttrs().getNeedConfirm()) {
                    hit.setLastModificationTime(System.currentTimeMillis() / 1000);
                    hit.getAttrs().setStatus(HitStatusEnum.CONFIRMED);
                    hitDao.saveOrUpdate(hit);
                }
                GpsLocation gpsLocation = hit.getAttrs().getGpsLocation();
                String handleCompanyCode = hit.getAttrs().getHandleCompanyCode();
                List<Car> carList = carService.queryByCompany(handleCompanyCode);
                List<String> carIds = carList.stream().map(Car::getId).collect(Collectors.toList());
                Point point = new Point(gpsLocation.getLongitude(), gpsLocation.getLatitude());
                List<AggregationOperation> aggregationList = new ArrayList<>();
                aggregationList.add(new GeoNearDocument(new Query(Criteria.where("car_id").in(carIds).and("time_stamp").gt(hit.getLastModificationTime() * 1000).lt(System.currentTimeMillis() - 30000)), point, "location", mergeDistance));
                Aggregation agg = Aggregation.newAggregation(aggregationList);
                List<InspectPicture> aggregate = inspectPictureDao.aggregate(agg);
                if (CollectionUtils.isNotEmpty(aggregate)) {
                    String str = zhonghaiClient.doReviewResult(hit.getId(), "1", "审核通过", "");
                    //复核成功逻辑
                    if (ObjectUtils.isNotEmpty(str) && str.contains("执行成功")) {
                        HistoryHit newHistoryHit = new HistoryHit();
                        newHistoryHit.setHitTime(System.currentTimeMillis() / 1000);
                        newHistoryHit.setSubjects(new ArrayList<>());
                        newHistoryHit.setHeightDiff(0);
                        newHistoryHit.setAngle(0f);
                        newHistoryHit.setRoadType(hit.getRoadType());
                        newHistoryHit.setWidth(0);
                        newHistoryHit.setType(hit.getType());
                        newHistoryHit.setSeverityType(hit.getSeverityType());
                        newHistoryHit.setLength(0f);
                        newHistoryHit.setHeadCount(0);
                        newHistoryHit.setFallDownNumber(0);
                        newHistoryHit.setComfortRate(0f);
                        newHistoryHit.setArea(0f);

                        HistoryHitAttrs historyHitAttrs = new HistoryHitAttrs();
                        historyHitAttrs.setSceneImage(aggregate.get(0).getUrl());
                        historyHitAttrs.setStatus(HitStatusEnum.CONFIRMED);
                        historyHitAttrs.setGpsLocation(hit.getAttrs().getGpsLocation());
                        newHistoryHit.setAttrs(historyHitAttrs);
                        hit.setLastModificationTime(System.currentTimeMillis() / 1000);
                        hit.getAttrs().setStatus(HitStatusEnum.CONFIRMED);
                        hit.getList().add(0, newHistoryHit);

                        hitDao.saveOrUpdate(hit);
                    }
                }
                String id = hit.getId();
                Criteria criteria = Criteria.where("_id").nin(id);
                Query queryOne = new Query(criteria);
                Hit one = hitDao.findOne(queryOne);
                HistoryHit historyHit = one.getList().get(0);
                HitStatusEnum status = historyHit.getAttrs().getStatus();
                HitStatusEnum status1 = one.getAttrs().getStatus();
                if(!status1.equals(status)) {
                    Update update = new Update().set("attrs.status", status);
                    hitDao.update(id, update);
                }
            } catch (Exception e) {
                log.error("reviewHit fail, fail message: " + e);
                e.printStackTrace();
            }
        });
    }

    /**
     * 每天凌晨12点更新一次
     */
    @Scheduled(cron = "0 0 12 * * ?", zone = "GMT+8:00")
//    @Scheduled(cron = "0/5 * * * * ?")
    public void updateZhongHaiData() {
        if (present) {
            return;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int year = calendar.get(Calendar.YEAR);
        String ym = ymSdf.format(new Date());
        //作业监管
        callZhongHaiInterface(ZH_METHOD_WORK_CHECK, "{\"pageNum\":4}");
        //考核得分1
        callZhongHaiInterface(ZH_METHOD_ASSESSMENT_SCORE, "{\"type\":\"year\",\"info\":\"" + year + "\"}");
        //考核得分2
        callZhongHaiInterface(ZH_METHOD_ASSESSMENT_SCORE, "{\"type\":\"month\",\"info\":\"" + ym + "\"}");
        //智能发现1
        callZhongHaiInterface(ZH_METHOD_SMART_DISCOVER, "{\"isDay\":\"isDay\"}");
        //智能发现2
        callZhongHaiInterface(ZH_METHOD_SMART_DISCOVER, "{\"isDay\":\"\"}");
        //投诉报表大类
        callZhongHaiInterface(ZH_METHOD_COMPLAIN_REPORT, "{\"year\":\"" + year + "\"}");
    }

    public String callZhongHaiInterface(String type, String arg) {
        String res = null;
        String token = zhTokenUtil.getLocalToken();
        String authorization = null;
        if (StringUtils.isNotBlank(token)) {
            authorization = zhonghaiClient.getAuthorization(token);
        }
        String host = ip + ":" + webServicePort + "/hbzs/";
        String requestData = String.format(template, "<m:hbzptInfo" +
                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
                "<arg0>" + type + "</arg0>" +
                "<arg1>" + arg + "</arg1>" +
                "</m:hbzptInfo>");
        //调用中海接口，如果查到数据，则在数据库中创建新数据
        try {
            if (StringUtils.isNotBlank(token)) {
                res = ZhonghaiClient.getDataFromZhonghai("http://" + host + "/services/BizWebService", "POST", requestData, authorization);
            }
        } catch (IOException e) {
            log.error("调用callZhongHaiInterface异常, error arg {}, error message {}", type, arg);
        }
        if (Objects.nonNull(res)) {
            int startIndex = res.indexOf("<return>") + 8;
            int endIndex = res.indexOf("</return>", startIndex);
            if (endIndex - 3 > startIndex) {
                String resSub = res.substring(startIndex, endIndex);
                //特判
                boolean enable = true;
                if (type.equals(ZH_METHOD_ASSESSMENT_SCORE)) {
                    List<AssessmentScore> assessmentScores = JSONArray.parseArray(resSub, AssessmentScore.class);
                    enable = !assessmentScores.stream().anyMatch(a -> a.getTotal() == null);
                }
                ZhongHai zhongHai = ZhongHai.builder().timeStamp(new Date().getTime() / 1000).type(type)
                        .arg(arg).data(res).enable(enable).build();
                zhongHaiDao.saveOrUpdate(zhongHai);
            }
        }
        //如果查不到数据，就不处理
        return res;
    }

    public String callZhongHaiInterface2(String type, String arg) {
        String res = null;
        String token = zhTokenUtil.getLocalToken();
        String authorization = null;
        if (StringUtils.isNotBlank(token)) {
            authorization = zhonghaiClient.getAuthorization(token);
        }
        String host = ip + ":" + webServicePort + "/hbzs/";
        String requestData = String.format(template, "<m:hbzptInfo" +
                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
                "<arg0>" + type + "</arg0>" +
                "<arg1>" + arg + "</arg1>" +
                "</m:hbzptInfo>");
        //调用中海接口，如果查到数据，则在数据库中创建新数据
        try {
            if (StringUtils.isNotBlank(token)) {
                res = ZhonghaiClient.getDataFromZhonghai("http://" + host + "/services/BizWebService", "POST", requestData, authorization);
            }
        } catch (IOException e) {
            log.error("调用callZhongHaiInterface2异常, error arg {}, error message {}", type, arg);
        }
        if (Objects.nonNull(res)) {
            int startIndex = res.indexOf("<return>") + 8;
            int endIndex = res.indexOf("</return>", startIndex);
            res = res.substring(startIndex, endIndex);
        }
        //如果查不到数据，就不处理
        return res;
    }

    public CompanyScoreResponse parseCompanyScoreJson(String s) {
        if (!s.startsWith("[")){
            s = "[{" + s;
        }
        if (!s.endsWith("]")){
            s = s + "}]";
        }
        JSONArray jsonArray = JSON.parseArray(s);
        CompanyScoreResponse response = new CompanyScoreResponse();
        List<UnitScoreInfo> unitScoreInfoList = new ArrayList<>();
        Double totalDeductScore = 0d;
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            UnitScoreInfo unitScoreInfo = new UnitScoreInfo();
            String section = jsonObject.getString("sections");
            if(StringUtils.isEmpty(section)){
                section = jsonObject.getString("section");
            }
            if (StringUtils.isEmpty(section)){
                continue;
            }
            Unit unit = unitDao.fetch(section);
            if (ObjectUtils.isEmpty(unit)) {
                continue;
            }
            unitScoreInfo.setUnitName(unit.getUnitName());
            JSONArray dataArray = jsonObject.getJSONArray("data");
            if (CollectionUtils.isNotEmpty(dataArray)) {
                for (int dataIndex = 0; dataIndex < dataArray.size(); dataIndex++) {
                    JSONObject dataObject = dataArray.getJSONObject(dataIndex);
                    UnitScoreInfo.UnitModuleScore moduleScore = unitScoreInfo.new UnitModuleScore();
                    String name = dataObject.getString("name");
                    JSONArray children = dataObject.getJSONArray("children");
                    int deductScore = 0;
                    List<UnitScoreInfo.DeductDetail> deductDetailList = new ArrayList<>();
                    for (int childIndex = 0; childIndex < children.size(); childIndex++) {
                        UnitScoreInfo.DeductDetail deductDetail = unitScoreInfo.new DeductDetail();
                        JSONObject childObject = children.getJSONObject(childIndex);
                        if (childObject.getInteger("deduct_score") != 0) {
                            Integer childDeductScore = childObject.getInteger("deduct_score");
                            deductScore += childDeductScore;
                            deductDetail.setDeductScore(childDeductScore);
                            String type = childObject.getString("name");
                            deductDetail.setType(type);
                            deductDetail.setDeductReason(childObject.getString("deduct_score_reason"));
                            deductDetailList.add(deductDetail);
                        }
                    }
                    moduleScore.setDeducts(deductDetailList);
                    moduleScore.setScore(100 - deductScore);
                    switch (name) {
                        case "规范化管理":
                            unitScoreInfo.setNormalization(moduleScore);
                            break;
                        case "智能管理":
                            unitScoreInfo.setSmart(moduleScore);
                            break;
                        case "专项扣分":
                            unitScoreInfo.setSpecial(moduleScore);
                            break;
                        default:
                            break;
                    }
                }
                double unitScore = unitScoreInfo.getNormalization().getScore() * 0.4 + unitScoreInfo.getSmart().getScore() * 0.6 - (100 - unitScoreInfo.getSpecial().getScore());
                unitScoreInfo.setScore(unitScore);
                totalDeductScore += (100 - unitScore);
                unitScoreInfoList.add(unitScoreInfo);
            }
            response.setScore(100 - totalDeductScore);
            response.setUnits(unitScoreInfoList);
        }
        return response;
    }

    @OpLog(description = "推送中海")
    public String client(Map map) { // 连接套接字方法
        DataInputStream dataInputStream = null;
        DataOutputStream dataOutputStream = null;
        String charsetName = "gbk";
        try { // 捕捉异常
            //todo:网络编程
            socket = new Socket(ip, port); // 实例化Socket对象，连接端口8080服务器
            new PrintWriter(socket.getOutputStream(), true);//建立通信通道，强行输出数据
            //发送数据
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            String message = JSON.toJSONString(map);
            log.info("推送数据：{}", message);
            // message = "要发送的数据===我是客户端";
            dataOutputStream.write(message.getBytes(charsetName));

            //接收服务端的数据
            StringBuilder stringBuilder = new StringBuilder();
            dataInputStream = new DataInputStream(socket.getInputStream());
            byte[] buf = new byte[1024];
            //这里用其他的流也可以啊，比如BufferedReader
            int len = dataInputStream.read(buf);
            if (len != -1) {
                stringBuilder.append(new String(buf, 0, len, charsetName));
            }
            dataInputStream.close();
            dataOutputStream.close();
            String receiveMessage = "" + stringBuilder;
            log.info("推送结果：{}", receiveMessage);
            return receiveMessage;
        } catch (Exception e) {
            log.error("推送中海异常, 异常信息: {}", e.getLocalizedMessage());
        } finally {
            try {
                if (dataOutputStream != null) {
                    dataOutputStream.close();
                }
                if (dataInputStream != null) {
                    dataInputStream.close();
                }
                if (socket != null && !socket.isClosed()) {
                    socket.close();
                }
            } catch (IOException e) {
                log.error("close socket met exception: {}", e);
            }
        }
        return null;
    }

    //道路病害
    public Map getDisease(String id) {
        Hit hit = hitDao.fetch(id);
        Map map = new HashMap();
        Map iddr = new HashMap();
        Map action = new HashMap();
        action.put("stime", sdf.format(new Date()));
        action.put("sid", hit.getId());
        action.put("devid", hit.getAttrs().getCarId());
        action.put("lgt", hit.getAttrs().getGpsLocation().getLongitude());
        action.put("lat", hit.getAttrs().getGpsLocation().getLatitude());
        String sceneImage = hit.getAttrs().getFrameImageUrl();
        if (StringUtils.isBlank(sceneImage)) {
            sceneImage = hit.getAttrs().getSceneImage();
        }
        String[] split = sceneImage.split("/");
        action.put("picName", split[split.length - 1]);
        action.put("url", sceneImage);
        String type = hit.getType();
        DiseaseConfigInfo diseaseConfigInfo = diseaseConfig.getMap().get(type);
        Integer stype = diseaseConfigInfo.getStype();
        action.put("stype", stype);
        String roadName = hit.getAttrs().getRoadName();
        if (StringUtils.isNotBlank(roadName)) {
            String[] roadSplit = roadName.split(",");
            action.put("roadName", roadSplit[0]);
        }else {
            action.put("roadName", "未获取道路名称");
        }
        action.put("projectid", "");
        iddr.put("info", action);
        map.put("iddr", iddr);
        return map;
    }

    // 根据我們的病害生成中海需要的推送结构
    public Map generateDiseaseMap(Hit hit, Integer stype) {
        Map map = new HashMap();
        Map iddr = new HashMap();
        Map action = new HashMap();
        action.put("stime", sdf.format(new Date()));
        action.put("sid", hit.getId());
        action.put("devid", hit.getAttrs().getCarId());
        action.put("lgt", hit.getAttrs().getGpsLocation().getLongitude());
        action.put("lat", hit.getAttrs().getGpsLocation().getLatitude());
        String frameImageUrl = hit.getAttrs().getFrameImageUrl();
        if (StringUtils.isBlank(frameImageUrl)) {
            frameImageUrl = hit.getAttrs().getSceneImage();
        }
        String[] split = frameImageUrl.split("/");
        action.put("picName", split[split.length - 1]);
        action.put("url", frameImageUrl);
        action.put("stype", stype);
        String roadName = hit.getAttrs().getRoadName();
        if (StringUtils.isNotBlank(roadName)) {
            String[] roadSplit = roadName.split(",");
            action.put("roadName", roadSplit[0]);
        }else {
            action.put("roadName", "未获取道路名称");
        }
        action.put("projectid", "");
        iddr.put("info", action);
        map.put("iddr", iddr);
        return map;
    }

    /**
     * 复核推送中海
     *
     * @param hitId     病害id
     * @param resultNum 状态， 1 通过， 2 不通过
     * @param picPath   图片地址
     * @param remarks   描述
     * @return
     * @throws Exception
     */
    @OpLog(description = "复核病害")
    public String doReviewResult(String hitId, String resultNum, String remarks, String picPath) throws Exception {
        String token = zhTokenUtil.getLocalToken();
        String authorization = getAuthorization(token);
        String host = ip + ":" + webServicePort + "/hbzs/";
        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
                "<SOAP-ENV:Body>%s" +
                "</SOAP-ENV:Body>" +
                "</SOAP-ENV:Envelope>";
        String data = String.format(dataTemplate, "<m:hbzptInfo" +
                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
                "<arg0>ytkjReviewResult</arg0>" +
                "<arg1>{\"taskNum\":\"" + hitId + "\",\"resultNum\":\"" + resultNum + "\",\"remarks\":\"" + remarks + "\",\"picUrl\":\"" + picPath + "\"}</arg1>" +
                "</m:hbzptInfo>");
        String rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
        log.info("reviewResult from zhonghai:{}", rlt);
        return rlt;
    }


    @OpLog(description = "查询道路病害数据")
    public String getRoadDiseaseData(String startTime,String endTime) throws Exception {
        String token = zhTokenUtil.getLocalToken();
        String authorization = getAuthorization(token);
        String host = ip + ":" + webServicePort + "/hbzs/";
        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
                "<SOAP-ENV:Body>%s" +
                "</SOAP-ENV:Body>" +
                "</SOAP-ENV:Envelope>";
        String data = String.format(dataTemplate, "<m:hbzptInfo" +
                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
                "<arg0>getRoadDiseaseData</arg0>" +
                "<arg1>{\"startTime\":\"" + startTime + "\",\"endTime\":\"" + endTime + "\"}</arg1>" +
                "</m:hbzptInfo>");
        String rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
        log.info("reviewResult from zhonghai:{}", rlt);
        return rlt;
    }

    // 从中海接口获得特定工单流程信息
    public String getZhongHaiTaskInfo(String taskNum) {
        String token = zhTokenUtil.getLocalToken();
        String authorization = getAuthorization(token);
        String host = ip + ":" + webServicePort + "/hbzs/";
        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
                "<SOAP-ENV:Body>%s" +
                "</SOAP-ENV:Body>" +
                "</SOAP-ENV:Envelope>";

        String data = String.format(dataTemplate, "<m:hbzptInfo" +
                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
                "<arg0>" + ZH_METHOD_GET_ADVICE + "</arg0>" +
                "<arg1>{\"taskNum\":\"" + taskNum +  "\"}</arg1>" +
                "</m:hbzptInfo>");
        String rlt = null;
        try {
            rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
        } catch (Exception e) {
            log.error("中海接口获取流程异常,流程id={}",taskNum);
            return null;
        }
        int startIndex = rlt.indexOf("<return>") + 8;
        int endIndex = rlt.indexOf("</return>", startIndex);
        if (startIndex >= endIndex) {
            return "";
        }
        String scoreDetail = rlt.substring(startIndex , endIndex );
        String result = scoreDetail.replace("\\\"", "\"");
//        log.info("收到中海接口返回的流程{}对应信息:{}",taskNum,result);
//        ZhongHai zhongHai = ZhongHai.builder().timeStamp(new Date().getTime() / 1000).type(ZH_METHOD_UNIT_SCORE)
//                .arg(id + "-" + yearMonth).data(result).build();
//        zhongHaiDao.saveOrUpdate(zhongHai);
        return result;
    }

    /**
     * 获取标段扣分详情
     *
     * @param id        管养单位id
     * @param yearMonth 年月
     * @return
     * @throws Exception
     */
    public String queryUnitScore(String id, String yearMonth) {
        Company company = companyDao.fetch(id);
        Set<String> units = company.getUnits();
        String unitString = String.join(",", units);
        String token = zhTokenUtil.getLocalToken();
        String authorization = getAuthorization(token);
        String host = ip + ":" + webServicePort + "/hbzs/";
        String dataTemplate = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"" +
                " SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
                "<SOAP-ENV:Body>%s" +
                "</SOAP-ENV:Body>" +
                "</SOAP-ENV:Envelope>";

        String data = String.format(dataTemplate, "<m:hbzptInfo" +
                " xmlns:m=\"http://intf.webservices.bizmodules.scdp.csnt.com/\">" +
                "<arg0>" + ZH_METHOD_UNIT_SCORE + "</arg0>" +
                "<arg1>{\"sections\":\"" + unitString + "\",\"yearMonth\":\"" + yearMonth + "\"}</arg1>" +
                "</m:hbzptInfo>");
        String rlt = null;
        try {
            rlt = getWebserviceResponse("http://" + host + "/services/BizWebService", "POST", data, authorization);
        } catch (Exception e) {
            log.error("中海接口获取标段得分异常");
            return null;
        }
        int startIndex = rlt.indexOf("<return>") + 8;
        int endIndex = rlt.indexOf("</return>", startIndex);
        if (startIndex >= endIndex) {
            return null;
        }
        String scoreDetail = rlt.substring(startIndex + 2, endIndex - 2);
        String result = scoreDetail.replace("\\\"", "\"");
        ZhongHai zhongHai = ZhongHai.builder().timeStamp(new Date().getTime() / 1000).type(ZH_METHOD_UNIT_SCORE)
                .arg(id + "-" + yearMonth).data(result).build();
        zhongHaiDao.saveOrUpdate(zhongHai);
        return result;
    }

    public String getAuthorization(String token) {
        //使用base64进行加密
        byte[] tokenByte = Base64.getEncoder().encode((username + ":" + token).getBytes());
        //将加密的信息转换为string
        String tokenStr = new String(tokenByte);
        return "Basic " + tokenStr;
    }

    public String retrieveReasonFromTaskInfoResponse(String response) {
        if (StringUtils.isBlank(response)) {
            return null;
        }
        try {
            TypeReference<List<TaskInfoResponse>> ref = new TypeReference<List<TaskInfoResponse>>() {};
            List<TaskInfoResponse> taskInfoResponseList = JsonUtils.StringConvertToList(response, ref);
            List<TaskInfoDetail> data = taskInfoResponseList.get(0).getData();
            if (data.isEmpty()) {
                return "";
            }
            List<TaskInfoDetail> collect = data.stream().sorted(Comparator.comparing(TaskInfoDetail::getCreatedate).reversed()).collect(Collectors.toList());
            boolean completed = false;
            for (TaskInfoDetail taskInfoDetail : collect) {
                if (taskInfoDetail.isRejectInfo()) {
                    return taskInfoDetail.getAdvice();
                } else if (taskInfoDetail.isCompleted()) {
                    completed = true;
                }
            }
            if (completed)
                return "已结案";
            // 尚无退单流程数据,等待重试
            return null;
        } catch (Exception e) {
            log.error("退单结果解析失败, response = {}",response);
            return null;
        }
    }

    public String getReasonFromZhongHaiTaskInfo(String taskNum) {
        String response = getZhongHaiTaskInfo(taskNum);
        if (response != null) {
            return retrieveReasonFromTaskInfoResponse(response);
        }
        return null;
    }
}
